<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html lang="zh-CN"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta http-equiv="Content-Language" content="zh-CN"><link href="stylesheet.css" media="all" rel="stylesheet" type="text/css">
<title>多字段索引</title>
<script> var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js?d286c55b63a3c54a1e43d10d4c203e75"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); </script>
</head><body class="SECT1">
<div>
<table summary="Header navigation table" width="100%" border="0" cellpadding="0" cellspacing="0">
<tr><th colspan="5" align="center" valign="bottom">PostgreSQL 8.2.3 中文文档</th></tr>
<tr><td width="10%" align="left" valign="top"><a href="indexes-types.html" accesskey="P">后退</a></td><td width="10%" align="left" valign="top"><a href="indexes.html">快退</a></td><td width="60%" align="center" valign="bottom">章11. 索引</td><td width="10%" align="right" valign="top"><a href="indexes.html">快进</a></td><td width="10%" align="right" valign="top"><a href="indexes-bitmap-scans.html" accesskey="N">前进</a></td></tr>
</table>
<hr align="LEFT" width="100%"></div>
<div class="SECT1"><h1 class="SECT1"><a name="INDEXES-MULTICOLUMN">11.3. 多字段索引</a></h1><a name="AEN16089"></a>
<p>一个索引可以定义在表中多个字段上。比如下面这样的表(把 <tt class="FILENAME">/dev</tt> 目录保存在一个数据库里)：</p>
<pre class="PROGRAMLISTING">CREATE TABLE test2 (
  major int,
  minor int,
  name varchar
);</pre>
<p>并且你经常做下面这样的查询：</p>
<pre class="PROGRAMLISTING">SELECT name FROM test2 WHERE major = <tt class="REPLACEABLE"><i>constant</i></tt> AND minor = <tt class="REPLACEABLE"><i>constant</i></tt>;</pre>
<p>那么在字段 <tt class="STRUCTFIELD">major</tt> 和 <tt class="STRUCTFIELD">minor</tt> 上联合定义一个索引是比较合适的做法，也就是：</p>
<pre class="PROGRAMLISTING">CREATE INDEX test2_mm_idx ON test2 (major, minor);</pre>
<p>目前，只有 B-tree 和 GiST 支持多字段索引。缺省最多可以声明 32 个字段(这个限制可以在编译 PostgreSQL 时改变，见 <tt class="FILENAME">pg_config_manual.h</tt> 文件)。</p>
<p>一个多字段的 B-tree 索引可以用在包含索引字段子集的查询条件里，不过，如果在前导字段(最左边)上有约束条件，那么效率最高。准确的规则是前导字段上的等于约束，加上第一个没有等于约束的非等于约束字段，将用于限制所扫描的索引范围。将检查这两个字段右边字段上的索引以减少对表的访问，但是并不减少需要扫描的索引。比如，假如我们有一个在 <tt class="LITERAL">(a, b, c)</tt> 上的索引，查询条件是 <tt class="LITERAL">WHERE a = 5 AND b &gt;= 42 AND c &lt; 77</tt> ，那么索引就需要先扫描所有 <tt class="LITERAL">a = 5</tt> 且 <tt class="LITERAL">b = 42</tt> ，直到所有 <tt class="LITERAL">a = 5</tt> 的记录扫描完毕。那些 <tt class="LITERAL">c &gt;= 77</tt> 的索引条目将被忽略，但是他们仍然会被扫描。这个索引原则上仍然会被用于那些在 <tt class="LITERAL">b</tt> 和/或 <tt class="LITERAL">c</tt> 上有约束，但是在 <tt class="LITERAL">a</tt> 上没有约束的查询，但是就必须扫描整个索引了。因此，在大多数这种情况下，优化器会选择顺序扫描表，而不使用索引。</p>
<p>一个多字段的 GiST 索引只能用于那些在前导字段上有查询条件的查询中。附加字段上的条件会限制索引返回的条目，但是第一个字段上的条件是决定需要扫描多少索引内容的最重要的字段。如果在第一个字段上只有很少的一些唯一的数值，那么 GiST 就相对来说不那么高效了，即使在附加字段上有许多独立的数值也如此。</p>
<p>当然，每个字段都必须和适合该索引类型的操作符一起使用；包含其它操作符的子句将不会被考虑。</p>
<p>使用多字段索引应该谨慎。在大多数情况下，在单字段上的索引就足够了，并且还节约时间和空间。除非表的使用模式非常固定，否则超过三个字段的索引几乎没什么用处。又见<a href="indexes-bitmap-scans.html">节11.4</a>获取有关不同索引设置的优缺点的讨论。</p>
</div>
<div>
<hr align="LEFT" width="100%">
<table summary="Footer navigation table" width="100%" border="0" cellpadding="0" cellspacing="0">
<tr><td width="33%" align="left" valign="top"><a href="indexes-types.html" accesskey="P">后退</a></td><td width="34%" align="center" valign="top"><a href="index.html" accesskey="H">首页</a></td><td width="33%" align="right" valign="top"><a href="indexes-bitmap-scans.html" accesskey="N">前进</a></td></tr>
<tr><td width="33%" align="left" valign="top">索引类型</td><td width="34%" align="center" valign="top"><a href="indexes.html" accesskey="U">上一级</a></td><td width="33%" align="right" valign="top">组合多个索引</td></tr>
</table>
</div>
</body></html>